/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Initial Developer of the Original Code is
*   Nick Kreeger
* Portions created by the Initial Developer are Copyright (C) 2006-2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*   Nick Kreeger <nick.kreeger@park.edu>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */

#import "MessageWindowService.h"
#import "MessageWindowController.h"
#import "MailWindowController.h"
#import "MessageAccountManager.h"
#import "MailboxItem.h"
#import "CHBrowserService.h"
#import "CHMsgService.h"
#import "AttachmentInfoViewController.h"
#import "Attachment.h"

#import "nsIMsgMailSession.h"
#import "nsMsgBaseCID.h"

class nsIMsgFolder;

static MessageWindowService* kMessageWindowService = nil;

@interface MessageWindowService(Private)

-(void)verifyAccounts;
-(void)openAttachment:(NSNotification*)aNotification;
-(void)xpcomTerminate:(NSNotification*)aNotification;

-(void)makeArrayObjects:(NSArray*)inArray performSelector:(SEL)aSelector;
-(void)makeArrayObjects:(NSArray*)inArray performSelector:(SEL)aSelector withObject:(id)aObject;

@end

@implementation MessageWindowService 

+(id)sharedInstance
{
  if (!kMessageWindowService)
    kMessageWindowService = [[MessageWindowService alloc] init];
  
  return kMessageWindowService;
}

-(id)init
{
  if ((self = [super init]))
  {
    mMsgService = new CHMsgService();
    mMsgService->Init(self);
    
    mCurrentMessageUri = nil;
    mIsMessageLoading = NO;
    mIsTransmitting = NO;
    
    mMailWindowControllers = [[NSMutableArray alloc] init];
    mMessageWindowControllers =  [[NSMutableArray alloc] init];
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(xpcomTerminate:)
                                                 name:XPCOMShutDownNotificationName
                                               object:nil];
    
    // Listen to open attachment events:
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(openAttachment:) 
                                                 name:kOpenAttachmentNotification 
                                               object:nil];
  }
  
  return self;
}

-(void)dealloc
{
  [[NSNotificationCenter defaultCenter] removeObserver:self];
  
  delete mMsgService;
  
  if (mCurrentMessageUri)
    [mCurrentMessageUri release];
  
  [mMailWindowControllers release];
  [mMessageWindowControllers release];
  
  [super dealloc];
}

-(void)createAndShowMailWindowController
{
  MailWindowController* mailWinController = [[MailWindowController alloc] init];
  [mailWinController showWindow:self];
  
  [mMailWindowControllers addObject:mailWinController];
  [mailWinController release];
}

-(MailWindowController*)currentMailWindowController
{
  if ([mMailWindowControllers count] == 0)
    return nil;
  
  //XXX hack for now, just return the lowest window
  return (MailWindowController*)[mMailWindowControllers objectAtIndex:0];
}

-(void)setMessageWindowDelegate:(id<MessageWindowDelegate>)aDelegate
{
  mMessageWindowDelegate = aDelegate;
  if (mMessageWindowDelegate)
    mMsgService->SetCurrentMsgWindow([mMessageWindowDelegate browserMessageView]);
}

-(void)xpcomTerminate:(NSNotification*)aNotification
{
  mMsgService->Shutdown();
}

-(void)openAttachment:(NSNotification*)aNotification
{
  Attachment* attachment = [(AttachmentInfoViewController*)[aNotification object] attachment];
  mMsgService->OpenAttachment([[attachment contentType] cString],
                              [[attachment url] cString],
                              [[attachment displayName] cString],
                              [[attachment uri] cString],
                              [attachment isExternalAttachment]);
}

-(void)initMessageWindow:(CHBrowserView*)aBrowserView
{
  mMsgService->InitNewMsgWindow(aBrowserView);
}

-(void)removeMessageWindow:(MessageWindowController*)aMessageWinController
{
  mMsgService->RemoveMsgWindow([aMessageWinController browserMessageView]);
  [mMessageWindowControllers removeObject:aMessageWinController];
}

-(nsIMsgWindow*)getTopmostMsgWindow
{
  nsCOMPtr<nsIMsgMailSession> msgSession = do_GetService(NS_MSGMAILSESSION_CONTRACTID);
  if (!msgSession)
    return nsnull;
  
  nsCOMPtr<nsIMsgWindow> msgWindow = nsnull;
  nsresult rv = msgSession->GetTopmostMsgWindow(getter_AddRefs(msgWindow));
  if (NS_FAILED(rv) || !msgWindow)
  {
#if DEBUG
    NSLog(@"ERROR: Could not get the topmost message window!");
#endif
    // If we ever get here consistently, we should try and access the first
    // msg window available in the array from |nsIMsgMailSession|.
    nsCOMPtr<nsISupportsArray> windowArray;
    msgSession->GetMsgWindowsArray(getter_AddRefs(windowArray));
    
    PRUint32 count;
    windowArray->Count(&count);
    if (count > 1)
    {
      nsCOMPtr<nsISupports> supports;
      rv = windowArray->GetElementAt(0, getter_AddRefs(supports));
      if (NS_SUCCEEDED(rv) && supports)
        msgWindow = do_QueryInterface(supports);
    }
  }
  
  return msgWindow;
}

-(void)openMessageWindowWithMessageHeader:(MessageHeader*)aMessageHeader
                               messageUri:(NSString*)aUri
                          andCharacterSet:(NSString*)aCharSet
{
  MessageWindowController* messageWinCont = [[MessageWindowController alloc] initWithMessageHeader:aMessageHeader
                                                                                        messageUri:aUri 
                                                                                   andCharacterSet:aCharSet];
  [[messageWinCont window] makeKeyAndOrderFront:self];
  [messageWinCont loadMessageUri];
  [mMessageWindowControllers addObject:messageWinCont];
  [messageWinCont release];
}

-(NSString*)currentMessageUri
{
  return mCurrentMessageUri;
}

-(void)loadMessageUri:(NSString*)aUriSpec
{
  mIsMessageLoading = YES;
  mCurrentMessageUri = [aUriSpec retain];
  mMsgService->OpenUri([aUriSpec cString]);
}

-(void)stopActiveUrl
{
  if (mIsMessageLoading)
    mMsgService->StopUrls();
}

-(BOOL)isRunningUrl
{
  return mIsMessageLoading;
}

-(BOOL)isTransmitting
{
  return mIsTransmitting;
}

-(void)getNewMessagesForMailboxItem:(MailboxItem*)aMailboxItem
{
  nsIMsgFolder* repMsgFolder = [aMailboxItem representedMsgFolder];
  mMsgService->GetNewMessages(repMsgFolder);
}

-(void)getNewMessagesForMailboxItems:(NSMutableArray*)aMailboxArray
{
  /* 
  * XXX kreeger, this doesn't work...
   NSEnumerator* mailboxesEnum = [aMailboxArray objectEnumerator];
   MailboxItem* curMailboxItem = nil;
   while ((curMailboxItem = [mailboxesEnum nextObject]))
   [self getNewMessagesForMailboxItem:curMailboxItem];
   */
}

#pragma mark MessageWindowDelegate

-(void)onMessageLoaded:(DummyMessageHeader*)aDummyMessageHeader
{
  mIsMessageLoading = NO;
  [mMessageWindowDelegate onMessageLoaded:aDummyMessageHeader];
}

-(void)onAttachmentsLoaded:(NSArray*)aAttachmentArray
{
  [mMessageWindowDelegate onAttachmentsLoaded:aAttachmentArray];
}

-(CHBrowserView*)browserMessageView
{
  return nil;
}

#pragma mark  MessageDataDelegate
// |MailWindowController| objects are the messgae data delegates to inform.

-(void)onTotalMessagesChanged
{
  [self makeArrayObjects:mMailWindowControllers performSelector:@selector(onTotalMessagesChanged)];
}

-(void)onTotalUnreadMessagesChanged
{
  [self makeArrayObjects:mMailWindowControllers performSelector:@selector(onTotalUnreadMessagesChanged)];
}

-(void)onNewMailBiffStateChanged
{
  [self makeArrayObjects:mMailWindowControllers performSelector:@selector(onNewMailBiffStateChanged)];
}

-(void)onStartTransmission
{
  mIsTransmitting = YES;
  [self makeArrayObjects:mMailWindowControllers performSelector:@selector(onStartTransmission)];
}

-(void)onStopTransmission
{
  mIsTransmitting = NO;
  [self makeArrayObjects:mMailWindowControllers performSelector:@selector(onStopTransmission)];
}

-(void)onStatusMessageUpdated:(NSString*)aStatusMessage
{
  [self makeArrayObjects:mMailWindowControllers performSelector:@selector(onStatusMessageUpdated:) withObject:aStatusMessage];
}

-(void)makeArrayObjects:(NSArray*)inArray performSelector:(SEL)aSelector
{
  id curObject;
  NSEnumerator* objectsEnum = [inArray objectEnumerator];
  while ((curObject = [objectsEnum nextObject]))
    [curObject performSelector:aSelector];
}

-(void)makeArrayObjects:(NSArray*)inArray performSelector:(SEL)aSelector withObject:(id)aObject
{
  id curObject;
  NSEnumerator* objectsEnum = [inArray objectEnumerator];
  while ((curObject = [objectsEnum nextObject]))
    [curObject performSelector:aSelector withObject:aObject];
}

@end
